The invention relates generally to a method and system in a computer system for modifying computer code in memory, and, more specifically, to a technique by which a computer program can modify itself in memory.
Libraries are groups of general-purpose routines that perform functions that may be useful to many different programs. It is common for programmers to design programs that call library routines in order to exploit the useful functions performed by the library routines without having to generate the code that performs those functions. Libraries may be divided into static libraries and dynamic libraries. Static libraries are linked once to each program that uses them during the development of the program, before the program is ever executed. Dynamic libraries, or DLLs, on the other hand, are linked automatically to programs that call them when such a program is executed. Dynamic libraries have achieved common use, because (A) a dynamic library may be shared by different programs that are using the dynamic library at the same time, requiring only a single copy of the dynamic library in memory instead of requiring a copy for every program; and (B) an old version a dynamic library may be easily replaced with a new version by replacing the file containing the old version with a file containing the new version. The programs that use a static library, on the other hand, are inextricably linked to the old version, and must be relinked to the new version in order to use the new version.
Dynamic libraries are designed to be loaded and called by other programs, or executable modules, such as application programs (applications) or other libraries. An application or library that calls a dynamic library is referred to herein as a xe2x80x9ccalling module.xe2x80x9d The dynamic library called by a calling module is called the xe2x80x9ctarget library.xe2x80x9d The code for every calling module for a particular target library must contain an instruction requesting that an operating system component, known as the loader, load the target library. When the loader receives a request to load a target library, the loader first determines whether the target library is already in memory and accessible to the calling module. If the target library is not already in memory and accessible to the calling module, then the loader retrieves the target library from secondary storage, stores the target library in memory, and initializes an reference count associated with the target library that indicates the number of times a calling module has requested to load the target library to one. If the target library is already in memory and accessible to the calling module, then the loader merely increments the target library""s existing reference count. The loader also provides to the calling module the address in memory at which the target library is stored, so that the calling module can determine the actual addresses of the functions in the target library in order to call them. When a calling module is terminating, or when it has determined that it will no longer be using a target library, the calling module executes an instruction requesting that the loader unload the target library. When the loader receives a request to unload a target library, the loader decrements the reference count for the target library. If the decremented reference count is equal to zero, then the requesting calling module was the only calling module still using the target library, and the loader removes the target library from memory. If the decremented reference count is greater than zero, then calling modules other than the requesting calling module are using the target library, and the loader does not remove the target library from memory.
Certain of the processors upon which modern computers are based support multiple words sizes. For instance, the microprocessors in the Intel 80386/80486/Pentium(trademark) series support both a 16-bit mode, in which words are comprised of 16 bits, and a 32-bit mode, in which words are comprised of 32 bits. In the 16-bit mode, programs written for 16-bit word size may execute; in the 32-bit mode, programs written for 32-bit word size may execute. While many operating systems are designed to operate such processors exclusively in a single word size mode, and thereby execute programs written for a single word size exclusively, it would be desirable for an operating system to switch such a processor between multiple word size modes in order to enable the execution of programs written for each word size. Specifically, it would be desirable for an operating system to switch the Intel series of microprocessors between 16-bit mode and 32-bit mode, in order to enable the execution of program modules written for both 16-bit word size and 32-bit word size, discussed herein as 16-bit modules and 32-bit modules, respectively.
In an operating system under which both 16-bit modules and 32-bit modules may execute, the scheme for loading dynamic libraries discussed above may be extended to permit 16-bit modules to utilize 16-bit dynamic libraries and 32-bit modules to utilize 32-bit dynamic libraries. Specifically, such an operating system would contain a 16-bit loader, invocable by a 16-bit calling module to load 16-bit target libraries. A 16-bit calling module could further use a standard 16-bit calling instruction to call functions in a loaded 16-bit target library. Similarly, such an operating system would contain a 32-bit loader, invocable by a 32-bit calling module to load 32-bit target libraries. A 32-bit calling module could further use a standard 32-bit calling instruction to call functions in a loaded 32-bit target library.
However, in an operating system under which both 16-bit modules and 32-bit modules may execute, it would also be useful to enable 16-bit modules to call 32-bit libraries, since this would enable the designers of 16-bit libraries to update their libraries to 32-bit libraries, which would remain compatible with existing 16-bit modules that presently call the 16-bit library. It would further be useful to enable 32-bit modules to call 16-bit libraries, since this would enable the designers of new 32-bit modules to utilize existing libraries that are only available in 16-bit form. Attempts to enable programs of one word size to call libraries of the other word size are hampered by the facts that compilers for calling modules of one word size cannot create calling instructions to functions in libraries of the other word size, that parameter values are formatted differently for functions in libraries of different word size, that calling modules of one word size can only utilize the loader for that word size which can only load libraries of that word size, and that it is impractical to require that a calling module of one word size be modified in order to be able to call a library of the other word size.
The present invention provides a software facility for performing self-patching of a computer program in memory. Such self-patching is useful, for example, where, for purposes of compatibility with other programs, an executable program must contain instructions that cannot be written into the executable program by the compiler used to create the executable program. In a preferred embodiment, a software facility patches a segment of executable code at runtime under the control of that code segment. The code segment preferably has a selected entry point, as well as a patching section and a patched section. In accordance with the facility, the patching section patches the patched section to change the contents of the patched section. When the code segment is executed a first time at the selected entry point, execution jumps from the beginning of the patched section to a point beyond the patched section to execute the patching section. When the patching section is executed, it patches the patched section. Finally, when the code segment is executed at the selection entry point after the patching section patches the patched section, the patched section is executed rather than the patching section. The invention produces a result termed xe2x80x9clazy patching,xe2x80x9d in which the patching of an executable code section that is to be patched is deferred until that executable code section is first executed. As a result, the extra cost of patching the executable code segment is deferred until after execution has begun, and may be avoided entirely in cases in which the executable code segment is never executed.